using System.Collections.Generic;

using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Options;

using TomNet.Core.Options;
using TomNet.Exceptions;
using TomNet.Extensions;

namespace TomNet.Core.Options
{
    /// <summary>
    /// TomNet 配置选项创建器
    /// </summary>
    public class TomNetOptionsSetup : IConfigureOptions<TomNetOptions>
    {
        private readonly IConfiguration _configuration;

        /// <summary>
        /// 初始化一个<see cref="TomNetOptionsSetup"/>类型的新实例
        /// </summary>
        public TomNetOptionsSetup(IConfiguration configuration)
        {
            _configuration = configuration;
        }

        /// <summary>Invoked to configure a TOptions instance.</summary>
        /// <param name="options">The options instance to configure.</param>
        public void Configure(TomNetOptions options)
        {

            SetDbContextOptions(options);
            SetUploadOptions(options);
            IConfigurationSection section;


            //JwtOptions
            section = _configuration.GetSection("TomNet:Jwt");
            JwtOptions jwt = section.Get<JwtOptions>();
            if (jwt != null)
            {
                if (jwt.Secret == null)
                {
                    jwt.Secret = _configuration["TomNet:Jwt:Secret"];
                }
                options.Jwt = jwt;
            }

            // RedisOptions
            section = _configuration.GetSection("TomNet:Redis");
            RedisOptions redis = section.Get<RedisOptions>();
            if (redis != null)
            {
                if (redis.Configuration.IsMissing())
                {
                    throw new TomNetException("配置文件中Redis节点的Configuration不能为空");
                }
                options.Redis = redis;
            }


            // CrossOptions
            section = _configuration.GetSection("TomNet:Cross");
            CrossOptions cros = section.Get<CrossOptions>();
            if (cros != null)
            {
                options.Cross = cros;
            }



            // SwaggerOptions
            section = _configuration.GetSection("TomNet:Swagger");
            SwaggerOptions swagger = section.Get<SwaggerOptions>();
            if (swagger != null)
            {
                if (swagger.Url.IsMissing())
                {
                    throw new TomNetException("配置文件中Swagger节点的Url不能为空");
                }
                options.Swagger = swagger;
            }
        }

        /// <summary>
        /// 文件上传配置
        /// </summary>
        private void SetUploadOptions(TomNetOptions options)
        {
            IConfigurationSection section = _configuration.GetSection("TomNet:UploadPolicies");
            IDictionary<string, UploadOptions> dict = section.Get<Dictionary<string, UploadOptions>>();
            if (dict == null || dict.Count == 0)
            {
                return;
            }

            //var repeated = dict.Values.GroupBy(m => m.PolicyName).FirstOrDefault(m => m.Count() > 1);
            //if (repeated != null)
            //{
            //    throw new TomNetException($"文件上传配置中，出现同名策略：{repeated.First().PolicyName}");
            //}

            foreach (KeyValuePair<string, UploadOptions> pair in dict)
            {
                pair.Value.PolicyName = pair.Key;
                options.UploadPolicies.Add(pair.Key, pair.Value);
            }
        }


        /// <summary>
        /// 数据库链接配置
        /// </summary>
        /// <param name="options"></param>
        private void SetDbContextOptions(TomNetOptions options)
        {
            IDictionary<string, TomNetDBContextOptions> dict;

            IConfigurationSection section = _configuration.GetSection("TomNet:DbContexts");
            dict = section.Get<Dictionary<string, TomNetDBContextOptions>>();



            if (dict == null || dict.Count == 0)
            {
                throw new TomNetException($"配置文件中不存在任何数据库上下文配置信息");
            }

            foreach (KeyValuePair<string, TomNetDBContextOptions> pair in dict)
            {
                pair.Value.DatabaseKey = pair.Key;
                options.DbContexts.Add(pair.Key, pair.Value);
            }
        }
    }
}